package wili.b1;

import java.util.List;
import java.util.Map;
import java.util.function.Predicate;
import java.util.stream.Collectors;

import wili.attrMapping._user.b1.exp.AndOrNode2;
import wili.attrMapping._user.b1.exp.Funb1;
import wili.attrMapping._user.b1.exp.MathExpB1;
import wili.attrMapping._user.b1.exp.Valueb1;
import wili.attrMapping._user.b1.exp.Varb1;
import wili.c.Ca;

/**
 * 
 * @author weila 2022年10月8日
 */
public class IncludesFun9 {
	public static AndOrNode2 includesFun_transform(AndOrNode2 andOrNode) {
		Predicate<AndOrNode2> manyEq_to_includesFunction = getTransformer_manyEq_to_includes();
		andOrNode.traverse(manyEq_to_includesFunction);
		return andOrNode;
	}

	static Predicate<AndOrNode2> getTransformer_manyEq_to_includes() {
		return new Predicate<AndOrNode2>() {
			@Override
			public boolean test(AndOrNode2 node) {
				// and {/VContInvnt} eq 'Y'
				if (node.isAnd == null || node.isAnd)
					return false;
				{// 把或式中的多个eq子，转成includes函数。eg. {ObjType} eq 2 or {ObjType} eq 3
				 // ~>[2,3].includes({ObjType})
				 // ({ObjType} eq 15 or {ObjType} eq 23 or {ObjType} eq 17) and {/DocType} eq 'I'
					List<AndOrNode2> sons = node.sons;
					if ("".isEmpty()) {
						if (sons.size() < 2)
							return false;
						List<AndOrNode2> eqList = sons.stream()
								.filter(e -> e.mathExp != null && e.mathExp.op.matches("===|eq"))
								.collect(Collectors.toList());
						Map<String, List<AndOrNode2>> varToEqNodesMap = AndOrNode2.groupList(eqList, (nod) -> {
							MathExpB1 exp = nod.mathExp;
							if (exp.ll instanceof Varb1) {
								if (exp.rr instanceof Valueb1)
									return exp.ll.getString(1);
							} else if (exp.ll instanceof Valueb1) {
								if (exp.rr instanceof Varb1)
									return exp.rr.getString(1);
							}
							return null;
						});
						// 有多个eq子左侧是相同变量，右侧是值。
						for (List<AndOrNode2> eqNodes : varToEqNodesMap.values()) {
							if (eqNodes.size() >= 2) {
								AndOrNode2 firstSon = eqNodes.get(0);
								sons.removeAll(eqNodes.subList(1, eqNodes.size()));
								List<MathExpB1> includesSons = eqNodes.stream().map(e -> e.mathExp)
										.collect(Collectors.toList());
								firstSon.mathExp = Funb1.newInst_includesFun(includesSons);
							}
						}
						if (sons.size() == 1) {
							node.toString();
							node.setMathExp(sons.get(0).mathExp);
						}
					}
				}
				return true;
			}
		};
	}

	public static void test() {
		String[][] test = { //
				{ "{aa} eq '13' or {aa} eq '14'", "['13','14'].includes({aa})" },
				{ "{bb} eq '13' or {bb} eq '14' or {bb} eq '15' or {cc} ne 'we'", //
						"['13','14','15'].includes({bb}) || {cc} !== 'we'" },
				{ "({aa} eq '13' or {bb} eq '14' or {aa} eq '21' or {bb} eq '11') and ({aa} eq 'we' or {bb} eq '14')",
						"['13','21'].includes({aa}) || ['14','11'].includes({bb}) && {aa} === 'we' || {bb} === '14'" } };
		for (int i = 0; i < test.length; i++) {
			String fm = test[i][0];
			String ret = FormulaTransform4b1.transform___(fm);
			Ca.log(1, "\n" + i + ">>> input:\n " + fm);
			Ca.log(1, i + ">>> output:\n " + ret);
			String st = test[i][1];
			if (!st.isEmpty()) {
				Ca.asert(ret.equals(st), "\n" + ret + " Not expect:\n" + st);
			}
			// break;
		}
	}

	public static void main(String[] args) {
		test();
	}
}
